﻿using Abp.Application.Services.Dto;
using Abp.Collections.Extensions;
using Abp.Domain.Repositories;
using Abp.Linq.Extensions;
using Abp.UI;
using Camc.Quality.Bop;
using Camc.Quality.DataDictionary;
using Camc.Quality.Quality;
using Camc.Quality.QualityAnalysis.RFormBase;
using Camc.Quality.QualityAnalysis.RFormClass;
using Camc.Quality.QualityAnalysis.RTechniqueEntity;
using Camc.Quality.RecordTable.FormBase;
using Camc.Quality.RecordTable.FormClass;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Camc.Quality.LeadCockpit
{
    public class LeadCockpitAppService : QualityAppServiceBase
    {
        private readonly IRepository<BopDesc, Guid> _bopDescRepository;
        private readonly IRepository<BopNode, Guid> _bopNodeRepository;
        private readonly IRepository<TechniqueEntity, Guid> _techniqueEntityRepository;
        private readonly IRepository<WorkStepEntity, Guid> _workStepEntityRepository;
        private readonly IRepository<TableBase, Guid> _tableBaseEntity;
        private readonly IRepository<RTableBase, Guid> _rTableBaseEntity;
        private readonly IRepository<VideoEntity, Guid> _videoEntityRepository;
        private readonly IRepository<RVideoEntity, Guid> _rVideoEntityRepository;
        private readonly IRepository<RbopNode, Guid> _rBopNodeRepository;
        private readonly IRepository<RTechniqueEntity, Guid> _rTechniqueEntity;
        private readonly IRepository<RWorkStepEntity, Guid> _rWorkStepEntity;
        private readonly IRepository<Sys_Code, Guid> _sysCodeRepository;

        public LeadCockpitAppService(IRepository<BopDesc, Guid> bopDescRepository,
                                     IRepository<BopNode, Guid> bopNodeRepository,
                                     IRepository<TechniqueEntity, Guid> techniqueEntityRepository,
                                     IRepository<WorkStepEntity, Guid> workStepEntityRepository,
                                     IRepository<TableBase, Guid> tableBaseEntity,
                                     IRepository<RTableBase, Guid> rTableBaseEntity,
                                     IRepository<VideoEntity, Guid> videoEntityRepository,
                                     IRepository<RVideoEntity, Guid> rVideoEntityRepository,
                                     IRepository<RbopNode, Guid> rBopNodeRepository,
                                     IRepository<RTechniqueEntity, Guid> rTechniqueEntity,
                                     IRepository<RWorkStepEntity, Guid> rWorkStepEntity,
                                     IRepository<Sys_Code, Guid> sysCodeRepository
                                     )
        {
            _bopDescRepository = bopDescRepository;
            _bopNodeRepository = bopNodeRepository;
            _techniqueEntityRepository = techniqueEntityRepository; ;
            _workStepEntityRepository = workStepEntityRepository;
            _tableBaseEntity = tableBaseEntity;
            _rTableBaseEntity = rTableBaseEntity;
            _videoEntityRepository = videoEntityRepository;
            _rVideoEntityRepository = rVideoEntityRepository;
            _rBopNodeRepository = rBopNodeRepository;
            _rTechniqueEntity = rTechniqueEntity;
            _rWorkStepEntity = rWorkStepEntity;
            _sysCodeRepository = sysCodeRepository;
        }
        /// <summary>
        /// 生产任务信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<ProductionAssignmentListDto>> GetProductionAssignmentList(GetProductionAssignmentListInput input)
        {
            var bopDesc = _bopDescRepository.GetAll().Where(s => s.ModelId != null && s.LotNoId != null);
            var bopNode = _bopNodeRepository.GetAll();
            var resultCount = await bopDesc.CountAsync();
            bopDesc = bopDesc.OrderBy(e => e.CreationTime).PageBy(input);
            IList<ProductionAssignmentListDto> productionAssignmentListDtos = new List<ProductionAssignmentListDto>();
            if (bopDesc.Count() == 0)
            {
                ProductionAssignmentListDto productionAssignmentListDto = new ProductionAssignmentListDto()
                {
                    Title = "",
                    ProcessRelationQuantity = 0,
                    Percent = { },
                    Flag = 1
                };
                productionAssignmentListDtos.Add(productionAssignmentListDto);
                return new PagedResultDto<ProductionAssignmentListDto>(resultCount, (List<ProductionAssignmentListDto>)productionAssignmentListDtos);
            }
            foreach (var item in bopDesc)
            {
                var bopNodeLevel2 = bopNode.Where(a => (a.BopDescId == item.Id) && (a.TechniqueEntityId != null) && (a.NodeLevel == 2));
                int processRelation = 0; //关联规程数量
                int notStarted = 0; //未开始数量
                int underImplementation = 0; //执行中数量
                int completed = 0; //已完成数量
                int notStartedPercent = 0;
                int underImplementationPercent = 0;
                int completedPercent = 0;
                var bopNodeLevel3 = bopNode.Where(a => (a.BopDescId == item.Id) && (a.TechniqueEntityId != null) && (a.NodeLevel == 3));
                if (bopNodeLevel2.Count() != 0)
                {
                    bopNodeLevel2 = from s in bopNodeLevel2
                                    where !bopNodeLevel3.Any(ss => ss.BopDescId == s.BopDescId)
                                    select s;
                }
                processRelation = bopNodeLevel2.Count() + bopNodeLevel3.Count();
                notStarted = bopNodeLevel2.Where(a => a.IsExport == 0).Count() + bopNodeLevel3.Where(a => a.IsExport == 0).Count();
                underImplementation = bopNodeLevel2.Where(a => a.IsExport == 1 && a.IsReturn == 0).Count() + bopNodeLevel3.Where(a => a.IsExport == 1 && a.IsReturn == 0).Count();
                completed = bopNodeLevel2.Where(a => a.IsExport == 1 && a.IsReturn == 1).Count() + bopNodeLevel3.Where(a => a.IsExport == 1 && a.IsReturn == 1).Count();
                if (processRelation != 0)
                {
                    notStartedPercent = (int)Math.Round((Double)notStarted / (Double)processRelation * 100);
                    underImplementationPercent = (int)Math.Round((Double)underImplementation / (Double)processRelation * 100);
                    completedPercent = (int)Math.Round((Double)completed / (Double)processRelation * 100);
                }
                int[] percent = { notStartedPercent, underImplementationPercent, completedPercent };
                var sysCode = _sysCodeRepository.GetAll();
                ProductionAssignmentListDto productionAssignmentListDto = new ProductionAssignmentListDto()
                {
                    //Title = item.Model + "   " + item.LotNo,
                    Title = sysCode.FirstOrDefault(s => s.Id == item.ModelId).Description + "   " + sysCode.FirstOrDefault(s => s.Id == item.LotNoId).Description,
                    ProcessRelationQuantity = processRelation,
                    Percent = percent,
                    Flag = 0
                };
                productionAssignmentListDtos.Add(productionAssignmentListDto);
            }
            return new PagedResultDto<ProductionAssignmentListDto>(resultCount, (List<ProductionAssignmentListDto>)productionAssignmentListDtos);
        }
        /// <summary>
        /// 质量采集信息
        /// </summary>
        /// <returns></returns>
        public async Task<QualityCollectionInfoListDto> GetQualityCollectionInfo()
        {
            var bopDesc = _bopDescRepository.GetAll().Where(s => s.ModelId != null && s.LotNoId != null);
            var bopNode = _bopNodeRepository.GetAll();
            var rbopNode = _rBopNodeRepository.GetAll();
            bopDesc = (from s in bopDesc
                       where bopNode.Any(ss => ss.BopDescId == s.Id)
                       select s).OrderBy(e => e.CreationTime);
            QualityCollectionInfoListDto qualityCollectionInfoListDto = new QualityCollectionInfoListDto();
            List<string> ProductName = new List<string>();
            List<int> QualityData = new List<int>();
            List<int> QualityCollectionData = new List<int>();
            foreach (var item in bopDesc)
            {
                //总项数
                var bopNodeList = bopNode.Where(s => s.BopDescId == item.Id && (s.NodeLevel == 2 || s.NodeLevel == 3));
                var tableBase = from tb in _tableBaseEntity.GetAll()
                                join work in _workStepEntityRepository.GetAll()
                                on tb.WorkStepEntityId equals work.Id
                                join bn in bopNodeList
                                on work.TechniqueEntityId equals bn.TechniqueEntityId
                                select tb;
                int tableBaseQuantity = tableBase.Count();
                int inspectionSignatureQuantity = tableBase.Where(s => s.InspectionSignature.Id != Guid.Empty).Count();
                int recordRequirementsQuantity = tableBase.Where(s => s.RecordRequirements.Id != Guid.Empty).Count();
                int multiMediaQuantity = tableBase.Where(s => s.MultiMedia.Id != Guid.Empty).Count();
                int measuredResultQuantity = tableBase.Where(s => s.MeasuredResult.Id != Guid.Empty).Count();
                int environmentQuantity = tableBase.Where(s => s.Environment.Id != Guid.Empty).Count();
                int videoQuantity = (from ve in _videoEntityRepository.GetAll()
                                     join work in _workStepEntityRepository.GetAll()
                                     on ve.WorkStepEntityId equals work.TechniqueEntityId
                                     join bn in bopNodeList
                                     on work.TechniqueEntityId equals bn.TechniqueEntityId
                                     select ve).Count();
                int qualityQuantity = tableBaseQuantity + inspectionSignatureQuantity + recordRequirementsQuantity + multiMediaQuantity + measuredResultQuantity + environmentQuantity + videoQuantity;
                //已采项数)
                var rbopNodeList = rbopNode.Where(s => s.RbopDescId == item.Id && (s.NodeLevel == 2 || s.NodeLevel == 3));
                var rtableBase = from tb in _rTableBaseEntity.GetAll()
                                 join work in _rWorkStepEntity.GetAll()
                                 on tb.RWorkStepEntityId equals work.Id
                                 join bn in rbopNodeList
                                 on work.RTechniqueEntityId equals bn.RtechniqueEntityId
                                 select tb;
                int rtableBaseQuantity = rtableBase.Count();
                int rinspectionSignatureQuantity = rtableBase.Where(s => s.InspectionSignature.Id != Guid.Empty).Count();
                int rrecordRequirementsQuantity = rtableBase.Where(s => s.RecordRequirements.Id != Guid.Empty).Count();
                int rmeasuredResultQuantity = rtableBase.Where(s => s.MeasuredResult.Id != Guid.Empty).Count();
                int renvironmentQuantity = rtableBase.Where(s => s.Environment.Id != Guid.Empty).Count();
                int rmultiMediaQuantity = rtableBase.Where(s => s.MultiMedia.Id != Guid.Empty).Count();
                int rvideoQuantity = (from ve in _rVideoEntityRepository.GetAll()
                                      join work in _rWorkStepEntity.GetAll()
                                      on ve.RWorkStepEntityId equals work.Id
                                      join bn in rbopNodeList
                                      on work.RTechniqueEntityId equals bn.RtechniqueEntityId
                                      select ve).Count();
                int qualityCollectedQuantity = rtableBaseQuantity + rinspectionSignatureQuantity + rrecordRequirementsQuantity + rmultiMediaQuantity + rmeasuredResultQuantity + renvironmentQuantity + rvideoQuantity;
                var model = _sysCodeRepository.FirstOrDefault(s => s.Id == item.ModelId);
                var lotNo = _sysCodeRepository.FirstOrDefault(s => s.Id == item.LotNoId);
                if (model != null && lotNo != null)
                {
                    var productName = model.Description + "/" + lotNo.Description;
                    ProductName.Add(productName);
                }
                else
                {
                    throw new UserFriendlyException("生产任务中的型号发次与用户字典中的不符");
                }
                ProductName.Add(model.Description + "/" + lotNo.Description);
                QualityData.Add(qualityQuantity);
                QualityCollectionData.Add(qualityCollectedQuantity);
                qualityCollectionInfoListDto.ProductName = ProductName;
                qualityCollectionInfoListDto.QualityData = QualityData;
                qualityCollectionInfoListDto.QualityCollectionData = QualityCollectionData;
            }
            return qualityCollectionInfoListDto;
        }
        /// <summary>
        /// 多媒体采集信息
        /// </summary>
        /// <returns></returns>
        public async Task<MultiMediaCollectionInfoDto> GetMultiMediaCollectionInfo()
        {
            var bopDesc = _bopDescRepository.GetAll().Where(s => s.ModelId != null && s.LotNoId != null); 
            var bopNode = _bopNodeRepository.GetAll();
            var rbopNode = _rBopNodeRepository.GetAll();
            bopDesc = (from s in bopDesc
                       where bopNode.Any(ss => ss.BopDescId == s.Id)
                       select s).OrderBy(e => e.CreationTime);
            MultiMediaCollectionInfoDto multiMediaCollectionInfoDto = new MultiMediaCollectionInfoDto();
            List<string> ProductName = new List<string>();
            List<int> MultiMediaData = new List<int>();
            List<int> MultiMediaCollectionData = new List<int>();
            foreach (var item in bopDesc)
            {
                //总项数
                var bopNodeList = bopNode.Where(s => s.BopDescId == item.Id && (s.NodeLevel == 2 || s.NodeLevel == 3));
                var tableBase = from tb in _tableBaseEntity.GetAll()
                                join work in _workStepEntityRepository.GetAll()
                                on tb.WorkStepEntityId equals work.Id
                                join bn in bopNodeList
                                on work.TechniqueEntityId equals bn.TechniqueEntityId
                                select tb;
                int tableBaseQuantity = tableBase.Count();
                int multiMediaQuantity = tableBase.Where(s => s.MultiMedia.Id != Guid.Empty).Count();
                //(from f in tableBase where f.MultiMedia.Id != Guid.Empty select f).Count();
                int videoQuantity = (from ve in _videoEntityRepository.GetAll()
                                     join work in _workStepEntityRepository.GetAll()
                                     on ve.WorkStepEntityId equals work.TechniqueEntityId
                                     join bn in bopNodeList
                                     on work.TechniqueEntityId equals bn.TechniqueEntityId
                                     select ve).Count();
                int multiMediaInfoQuantity = multiMediaQuantity + videoQuantity;
                //已采项数
                var rbopNodeList = rbopNode.Where(s => s.RbopDescId == item.Id && (s.NodeLevel == 2 || s.NodeLevel == 3));
                var rtableBase = from tb in _rTableBaseEntity.GetAll()
                                 join work in _rWorkStepEntity.GetAll()
                                 on tb.RWorkStepEntityId equals work.Id
                                 join bn in rbopNodeList
                                 on work.RTechniqueEntityId equals bn.RtechniqueEntityId
                                 select tb;
                int rtableBaseQuantity = rtableBase.Count();

                int rmultiMediaQuantity = rtableBase.Where(s => s.MultiMedia.Id != Guid.Empty).Count();
                //(from f in rtableBase where f.MultiMedia.Id != Guid.Empty select f).Count();
                int rvideoQuantity = (from ve in _rVideoEntityRepository.GetAll()
                                      join work in _rWorkStepEntity.GetAll()
                                      on ve.RWorkStepEntityId equals work.Id
                                      join bn in rbopNodeList
                                      on work.RTechniqueEntityId equals bn.RtechniqueEntityId
                                      select ve).Count();
                int multiMediaCollectedInfoQuantity = rmultiMediaQuantity + rvideoQuantity;
                //var sysCode = _sysCodeRepository.GetAll();
                var model = _sysCodeRepository.FirstOrDefault(s => s.Id == item.ModelId);
                var lotNo = _sysCodeRepository.FirstOrDefault(s => s.Id == item.LotNoId);
                if (model != null && lotNo != null)
                {
                    var productName = model.Description + "/" + lotNo.Description;
                    ProductName.Add(productName);
                }
                else 
                {
                    throw new UserFriendlyException("生产任务中的型号发次与用户字典中的不符");
                }
                    //ProductName.Add((sysCode.FirstOrDefault(s => s.Id == item.ModelId).Description + "/" + sysCode.FirstOrDefault(s => s.Id == item.LotNoId).Description).ToString());
                    MultiMediaData.Add(multiMediaInfoQuantity);
                    MultiMediaCollectionData.Add(multiMediaCollectedInfoQuantity);
                    multiMediaCollectionInfoDto.ProductName = ProductName;
                    multiMediaCollectionInfoDto.MultiMediaData = MultiMediaData;
                    multiMediaCollectionInfoDto.MultiMediaCollectionData = MultiMediaCollectionData;
            }
            return multiMediaCollectionInfoDto;
        }
        /// <summary>
        /// PAD任务信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<PagedResultDto<PadInfoListDto>> GetPadInfoList(GetPadInfoListInput input)
        {
            var padList = _bopNodeRepository.GetAll().Where(a => a.IsExport == 1 && a.IsReturn == 0 && a.PadId != null).OrderBy(a => a.CreationTime).GroupBy(a => a.PadId).Select(a => a.First());
            var resultCount = padList.Count();
            List<PadInfoListDto> padInfoListDtos = new List<PadInfoListDto>();
            if (resultCount == 0)
            {
                return new PagedResultDto<PadInfoListDto>(resultCount, padInfoListDtos);
            }
            padList = padList.OrderBy(e => e.CreationTime).PageBy(input);
            foreach (var item in padList)
            {
                var techList = _bopNodeRepository.GetAll().Where(a => a.PadId == item.PadId && a.IsReturn == 0);
                var padInfoListDto = new PadInfoListDto()
                {
                    PadName = item.PadName,
                    DownloadProcessQuantity = techList.Count(),
                    PadId = item.PadId
                };
                padInfoListDtos.Add(padInfoListDto);
            }
            foreach (var pi in padInfoListDtos)
            {
                var techList = _bopNodeRepository.GetAll().Where(a => a.PadId == pi.PadId && a.IsReturn == 0 && a.PadId != null);
                List<TechniqueListDto> techniqueListDtos = new List<TechniqueListDto>();
                foreach (BopNode bopNode in techList)
                {
                    var tech = _techniqueEntityRepository.FirstOrDefault(s => s.Id == bopNode.TechniqueEntityId);
                    if (tech != null)
                    {
                        var bopDesc = _bopDescRepository.FirstOrDefault(d => d.Id == bopNode.BopDescId);
                        var sysCode = _sysCodeRepository.GetAll();
                        var model = "";
                        var lotNo = "";
                        if (bopDesc.ModelId != null)
                        {
                            model = sysCode.FirstOrDefault(s => s.Id == bopDesc.ModelId).Description;
                        }
                        if (bopDesc.LotNoId != null)
                        {
                            lotNo = sysCode.FirstOrDefault(s => s.Id == bopDesc.LotNoId).Description;
                        }
                        TechniqueListDto techniqueListDto = new TechniqueListDto()
                        {
                            ModuleName = tech.ModuleName,
                            Model = model,
                            LotNo = lotNo,
                            TechniqueNumber = tech.TechniqueNumber,
                            ExportDate = bopNode.ExportDate,
                            ModuleCode = tech.ModuleCode,
                        };
                        techniqueListDtos.Add(techniqueListDto);
                    }
                }
                pi.TechniqueListDto = techniqueListDtos;
            }
            return new PagedResultDto<PadInfoListDto>(resultCount, padInfoListDtos);
        }
    } 
}
